using System;
using System.Collections.Generic;

namespace needle.Services.astra.Collections
{
	/// <summary>
	/// Hierarchy aware list of items, which can be limitted to its subset.
	/// There can be two kinds of items in this list:
	/// - item of <typeparamref name="T"/> type
	/// - item of <see cref="ISubsetListBase{T}"/> type.
	/// </summary>
	/// <remarks>
	/// Implementation of <see cref="ISubsetListBase{T}"/> in this interface behaves like if this list contains only items of type <typeparamref name="T"/> from all hierarchical levels. The order of items is the same as order of all leaves after they are "expanded" like in a tree.
	/// Example of items:
	/// 
	/// <see cref="ISubsetListBase{T}"/>
	///		<see cref="ISubsetListBase{T}"/>
	///			T0
	///		T1
	///		T2
	///	T3
	/// 
	/// In this case the order of items is given by hierarchical index (number #) after T in name of item T#.
	/// </remarks>
	/// <typeparam name="T">Item type.</typeparam>
	public interface IHierarchicalSubsetList<T> : ISubsetListBase<T>, IList<object>
	{
		/// <summary>
		/// Full list.
		/// </summary>
		IList<object> List
		{
			get;
		}

		/// <summary>
		/// Whether item at <paramref name="index"/> implements <see cref="ISubsetListBase{T}"/>.
		/// </summary>
		/// <param name="index">Outer index.</param>
		/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is invalid.</exception>
		bool IsItemSubsetList(int index);
		/// <summary>
		/// Gets item implementing <see cref="ISubsetListBase{T}"/> at <paramref name="index"/>.
		/// </summary>
		/// <param name="index">Outer index.</param>
		/// <returns>Subset list if the item implements <see cref="ISubsetListBase{T}"/>, otherwise null.</returns>
		/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is invalid.</exception>
		ISubsetListBase<T> GetItemSubsetList(int index);
		/// <summary>
		/// Number of <typeparamref name="T"/> items in item at <paramref name="index"/>.
		/// </summary>
		/// <param name="index">Outer index.</param>
		/// <returns>
		/// If <see cref="IsItemSubsetList"/> is true, returns <see cref="ISubsetListBase{T}.TCount"/>, otherwise 1.
		/// </returns>
		/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is invalid.</exception>
		int GetItemTCount(int index);
		/// <summary>
		/// Hierarchical index of the first <typeparamref name="T"/> subitem in item at <paramref name="index"/>.
		/// </summary>
		/// <param name="index">Outer index.</param>
		/// <returns>
		/// Hierarchical index.
		/// If <see cref="IsItemSubsetList"/> is true for item at <paramref name="index"/> and it is empty subset list, returns hierarchical index of previous item`s last subitem if it exists, otherwise 0.
		/// </returns>
		/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is invalid.</exception>
		int GetItemTStartIndex(int index);
		/// <summary>
		/// Hierarchical index of the last <typeparamref name="T"/> subitem in item at <paramref name="index"/>.
		/// </summary>
		/// <param name="index">Outer index.</param>
		/// <returns>
		/// <see cref="GetItemTStartIndex"/> + Max(0, <see cref="GetItemTCount"/> - 1).
		/// </returns>
		/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is invalid.</exception>
		int GetItemTEndIndex(int index);
	}
}
